package com.sxhalo.fsms.quartz;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

import com.sxhalo.fsms.domain.DeviceAlarmRecord;
import com.sxhalo.fsms.domain.FactDevice;
import com.sxhalo.fsms.domain.FactDeviceAlarmRule;
import com.sxhalo.fsms.domain.MotorRunningData;
import com.sxhalo.fsms.service.IDeviceAlarmRecordService;
import com.sxhalo.fsms.service.IFactDeviceAlarmRuleService;
import com.sxhalo.fsms.service.IFactDeviceService;
import com.sxhalo.fsms.util.CacheUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sxhalo.fsms.socket.WebSocketServer;
import com.sxhalo.fsms.util.DateUtil;

@DisallowConcurrentExecution //作业不并发
@Component
public class ScheduledAlarmTask implements Job {

	@Autowired
	private RedisTemplate<String, ?> redisTemplate;
	@Autowired
	private IDeviceAlarmRecordService alarmRecordService;

    @Autowired
    private IFactDeviceAlarmRuleService alarmRuleService;

	ObjectMapper objectMapper = new ObjectMapper();
	@Autowired
	private IFactDeviceService deviceService;

	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		// NULL不参与序列化
        objectMapper.setSerializationInclusion(Include.NON_NULL);

		System.out.println("ScheduledAlarmTask定时任务" + DateUtil.FormatTime(new Date()));
		//redis 连接失败 如何处理
		try {
			Long startTime = System.currentTimeMillis();
			//查询自定义报警规则
			List<FactDeviceAlarmRule> rules= getAlarmRule(); //查询所有未处理的报警信息
			List<DeviceAlarmRecord> saveAlarmRecordList = new ArrayList<DeviceAlarmRecord>();
			//从缓存中读取数据
			//Set<String> keys = redisTemplate.keys("*");
			List<FactDevice> deviceTypes=getDevices();

			HashOperations<String, Object, Object> redis = redisTemplate.opsForHash();
		//	keys.remove("AlarmDevice");
			int cdeviceId;
			for (FactDevice device : deviceTypes) {

				Map<Object, Object> rowData= redis.entries(device.getDeviceId().toString());
				//报警状态
				Integer alarm =rowData.get("Alarm")==null?0: Integer.parseInt(rowData.get("Alarm").toString());
				//脱口状态
				Integer trip = rowData.get("Trip")==null?0: Integer.parseInt(rowData.get("Trip").toString());

//				cdeviceId=Integer.parseInt(deviceId);
				cdeviceId=device.getDeviceId();
                //掉线
				if(rowData.size()==0||(rowData.get("Online")!=null&&rowData.get("Online").toString().equals("0"))){
					DeviceAlarmRecord record=new DeviceAlarmRecord();
					record.setDeviceId(cdeviceId);
					record.setAlarmLevel(AlarmEnum.LevelFault.getCode());
					record.setAttrId(DeviceAttrEnum.Online.getCode());
					record.setAlarmValue("掉线");
					record.setDefectSource(AlarmEnum.SourceSystem.getCode());
					record.setAlarmType(AlarmEnum.CategoryHigh.getCode());
					saveAlarmRecordList.add(record);


				//系统报警/跳闸
				}else if(alarm == 1||trip==1) {
					//根据报警码或得报警的字段
					DeviceAlarmRecord record=new DeviceAlarmRecord();

					if(trip==1){
						record.setAlarmLevel(AlarmEnum.LevelFault.getCode());
						record.setAlarmValue(rowData.get("TripCode").toString());
					}else{
						record.setAlarmValue(rowData.get("AlarmCode").toString());
						if(device.getDeviceTypeId()==1){
							record.setAlarmLevel(AlarmEnum.LevelFault.getCode());
						}else{
							record.setAlarmLevel(AlarmEnum.LevelAlarm.getCode());
						}
					}
					record.setDeviceId(cdeviceId);
				   // record.setAlarmLevel(AlarmEnum.LevelSystem.getCode());
				   record.setAlarmType(AlarmEnum.CategoryHigh2.getCode());
				   record.setDefectSource(AlarmEnum.SourceSelf.getCode());
				   saveAlarmRecordList.add(record);

				//自定义报警规则
				} else{
                    for(FactDeviceAlarmRule rule:rules){
						int alarmStates=0;
                    	if(rule.getDeviceId()==null||rule.getDeviceId().equals(cdeviceId)){
                          DeviceAttrEnum attrEnum=DeviceAttrEnum.getEnumByKey(rule.getAttrId());
                          if(attrEnum!=null){
                              if(rowData.get(attrEnum.getMsg())==null){
                              	continue;
							  }
							  BigDecimal  attrValue=new BigDecimal(rowData.get(attrEnum.getMsg())==null?"0":rowData.get(attrEnum.getMsg()).toString());
                              BigDecimal  minValue=rule.getMinValue()!=null?new BigDecimal(rule.getMinValue()):null;
                              BigDecimal  maxValue=rule.getMaxValue()!=null?new BigDecimal(rule.getMaxValue()):null;

							  if(rule.getMinValue()!=null&&rule.getMinValue()!=null){
									if(attrValue.compareTo(minValue)==-1||attrValue.compareTo(maxValue)==1||attrValue.compareTo(maxValue)==0){
									alarmStates=1;
								}
							  }else if(rule.getMinValue()!=null){
								  if(attrValue.compareTo(minValue)==-1){
									  alarmStates=1;
								  }
							  }else{
								  if(attrValue.compareTo(maxValue)==1){
									  alarmStates=1;
								  }
							  }

							  //如果报警 插入记录
							  if(alarmStates==1){
								  DeviceAlarmRecord record=new DeviceAlarmRecord();
								  record.setDeviceId(cdeviceId);
								  record.setAttrId(rule.getAttrId());
								  record.setAlarmValue(rowData.get(attrEnum.getMsg()).toString());
								  record.setRuleId(rule.getId());
								  record.setAlarmLevel(rule.getAlarmLevel());
								  record.setAlarmType(rule.getAlarmType());
								  record.setDefectSource(AlarmEnum.SourceSystem.getCode());
								  saveAlarmRecordList.add(record);
							  }
                          }
						}
                    	if(rule.getDeviceId()>cdeviceId) break;
					}

                }

			}

			Long runTime = System.currentTimeMillis()-startTime;
			System.out.println(" - [AlarmTask用时, "+(runTime/1000)+"秒] -");

			if(saveAlarmRecordList.size()>0){
				alarmRecordService.foreachInsert(saveAlarmRecordList);
				List<DeviceAlarmRecord> alarmRecord=alarmRecordService.findWhereList("state=0","create_time desc,alarm_type asc,alarm_level asc");
				Map<String, Object> msgData = new HashMap<String, Object>();
				msgData.put("AlarmData",alarmRecord);
				//报警数据发送
				WebSocketServer.sendMessage(msgData);
			}

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(" ---- [redis没连上] ----");
		}
		
		RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		
	}



	//type 0系统报警 1 自定义报警
	private Boolean recordIsSaved(DeviceAlarmRecord record,List<DeviceAlarmRecord> untreatedAlarmRecordList,Integer type){
//		for(DeviceAlarmRecord untreatedAlarmRecord:untreatedAlarmRecordList){
//
//			if(record.getDeviceId().equals(untreatedAlarmRecord.getDeviceId())){
//				//系统报警判断值
//				if(type==0){
//					if(record.getAlarmValue().equals(untreatedAlarmRecord.getAlarmValue())){
//						return true ;
//					}else{
//						return false;
//					}
//				}else if(record.getAttrId().equals(untreatedAlarmRecord.getAttrId())){
//
//					return true ;
//				}
//				return false;
//			}
//			if(untreatedAlarmRecord.getDeviceId()>record.getDeviceId()){
//				return false;
//			}
//		}
		return false;

	}


	private void getData(String id,	HashOperations<String, Object, Object> redis){

		Map<Object, Object> rowData = CacheUtil.get(id);
		if(rowData==null){
			rowData = redis.entries(id);
			CacheUtil.put(id,rowData);
		}
	}

	private 	List<FactDevice> getDevices(){
		List<FactDevice> deviceTypes=null;
		Object devices=CacheUtil.getObject("devices");
		if(devices==null){
			deviceTypes=deviceService.getTypeList("");
			CacheUtil.putObject("devices",deviceTypes);
		}else{
			deviceTypes=(List<FactDevice> )devices;
		}
		return  deviceTypes;
	}


	private List<FactDeviceAlarmRule> getAlarmRule(){
		List<FactDeviceAlarmRule> rules=null;
		Object ruleObject=CacheUtil.getObject("rules");
		if(ruleObject==null){
			rules=alarmRuleService.findWhereList("delete_flag=0 and use_state=1 and attr_id is not null and ( max_value is not null or min_value is not null) ","device_id asc,alarm_type asc,alarm_level asc");
			CacheUtil.putObject("rules",rules);
		}else{
			rules=(List<FactDeviceAlarmRule> )ruleObject;
		}
		return  rules;
	}

}
